package ca.scotthyndman.as2haxe.dom;

import java.util.ArrayList;
import java.util.List;

import ca.scotthyndman.as2haxe.dom.visitor.IVisitor;

/**
 * Represents a try statement.
 */
public class ASTryStatement extends ASStatement {

	/**
	 * The "catches" structural property of this node type.
	 */
	public static final ASChildListPropertyDescriptor CATCHES_PROPERTY = new ASChildListPropertyDescriptor(
			ASTryStatement.class, "catches", ASCatchStatement.class);

	/**
	 * The "body" structural property of this node type.
	 * 
	 * @since 3.0
	 */
	public static final ASChildPropertyDescriptor BODY_PROPERTY = new ASChildPropertyDescriptor(
			ASTryStatement.class, "body", ASBlock.class, true);

	/**
	 * A list of property descriptors (element type:
	 * {@link ASPropertyDescriptor}), or null if uninitialized.
	 */
	private static final List<ASPropertyDescriptor> PROPERTY_DESCRIPTORS;

	static {
		List<Object> properyList = new ArrayList<Object>(3);
		createPropertyList(ASTryStatement.class, properyList);
		addProperty(CATCHES_PROPERTY, properyList);
		addProperty(BODY_PROPERTY, properyList);
		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
	}

	/**
	 * Returns a list of structural property descriptors for this node type.
	 * Clients must not modify the result.
	 * 
	 * @return a list of property descriptors
	 */
	public static List propertyDescriptors() {
		return PROPERTY_DESCRIPTORS;
	}

	//
	// ======== MEMBERS
	//

	ASBlock body;

	List<ASTNode> catches = new ASTNode.NodeList(CATCHES_PROPERTY);

	//
	// ======== CONSTRUCTION
	//

	/**
	 * Constructs a new instance of ASTryStatement
	 * 
	 * @param ast
	 *            The abstract syntax tree that owns this element
	 */
	public ASTryStatement(AST ast) {
		super(ast);
	}

	//
	// ======== GETTERS AND SETTERS
	//

	public ASBlock getBody() {
		return body;
	}

	public void setBody(ASBlock body) {
		if (body == null) {
			throw new IllegalArgumentException();
		}
		ASTNode oldChild = this.body;
		preReplaceChild(oldChild, body, BODY_PROPERTY);
		this.body = body;
		postReplaceChild(oldChild, body, BODY_PROPERTY);
	}

	public List<ASTNode> getCatches() {
		return catches;
	}

	//
	// ======== INTERNAL GETTER / SETTER
	//

	/**
	 * internal get set implementation
	 */
	final ASTNode internalGetSetChildProperty(
			ASChildPropertyDescriptor property, boolean get, ASTNode child) {
		if (property == BODY_PROPERTY) {
			if (get) {
				return getBody();
			} else {
				setBody((ASBlock) child);
				return null;
			}
		}
		// allow default implementation to flag the error
		return super.internalGetSetChildProperty(property, get, child);
	}

	/**
	 * Internal
	 */
	final List<ASTNode> internalGetChildListProperty(
			ASChildListPropertyDescriptor property) {
		if (property == CATCHES_PROPERTY) {
			return getCatches();
		}
		// allow default implementation to flag the error
		return super.internalGetChildListProperty(property);
	}

	// TODO toString

	@Override
	public void accept(IVisitor as2Visitor, boolean visitChilds) {
		visitChilds = as2Visitor.visit(this);

		if (!visitChilds) {
			return;
		}

		getBody().accept(as2Visitor, visitChilds);
		for (ASTNode ctch : getCatches()) {
			((ASCatchStatement) ctch).accept(as2Visitor, visitChilds);
		}
	}
}
